import json
import re
from django import http
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
# Create your views here.
from django_redis import get_redis_connection

from apps.users.models import User
from django.contrib.auth import login
#1.导入
import logging
#2.创建(获取)日志实例
from apps.users.utils import generic_verify_email_url, check_verify_email_token
from utils.response_code import RETCODE
from utils.views import LoginRequiredJsonMixin

logger = logging.getLogger('django')


"""
功能点如何分析:
    1.需要依靠经验
    2.看其他网站的类似功能
注册页面的功能点:
    1.用户名:
        不能重复
        有长度限制
    2.密码:
        有长度限制
        数字和字母
    3.确认密码:
        需要和密码一致
    4.手机号
        符合要求
        不能重复
    5.图片验证码
        后台实现
        作用: 区分人和计算机的
        服务于: 短信验证码(发送短信花钱)
    6.短信验证码
        后台实现
        发送短信前先验证 图片验证码
    7.用户点击注册按钮的时候
        必须保存: 用户名,密码和手机号
        原因: 我们在登陆的时候需要使用这三个字段
    8.同意按钮
        需要点击同意

需求分析分析出来之后:
    1.先分析模型
    2.再众多功能中,找一个功能来入手,不要考虑很多的功能点(哪个简单,会哪个就先做哪个)
    3.把最难的功能放在最后
"""

"""
具体需求:
    当用户点击注册按钮的时候,需要让前端将 用户名,密码,确认密码,手机号,是否同意协议 提交给后台

后台:
    1.先确定路由和提交方式: POST      register/

        提取URL的特定部分，如/weather/beijing/2018，可以在服务器端的路由中用正则表达式截取；
        register/itcast/1234567890/1234567890/18212345678/on/

        查询字符串（query string)，形如key1=value1&key2=value2；
        register?itcast/1234567890/1234567890/18212345678/on/

        请求体（body）中发送的数据，比如表单数据、json、xml

    2.根据需求把大体步骤写下来[后端不相信前端提交的任何数据]
        ①接收数据
        ②验证数据
        ③保存数据
        ④返回相应

    3.具体实现的思路(步骤)
        ①接收数据 request.POST
        ②分别获取数据 username,password
        ③判断要求的数据是否齐全 [少参数就没有必要继续验证了]
        ④验证用户名
        ⑤验证密码
        ⑥验证确认密码
        ⑦验证手机号
        ⑧验证是否同意协议
        ⑨保存数据
        ⑩跳转首页,返回相应

    4.添加断点
        在函数的入库处,添加
     作用:
        ① 查看程序运行过程中的变量数据
        ② 一步一步的来梳理业务逻辑
        ③ 当我们验证某一行代码的时候可以添加断点
"""
class RegisterView(View):

    def get(self,request):

        return render(request,'register.html')

    def post(self,request):
        # ①接收数据 request.POST
        data=request.POST
        # ②分别获取数据 username,password
        username=data.get('username')
        password=data.get('password')
        password2=data.get('password2')
        mobile=data.get('mobile')
        allow=data.get('allow')
        sms_code_client = data.get('sms_code')
        # ③判断要求的数据是否齐全 [少参数就没有必要继续验证了]
        # all([username,password,password2,mobile,allow])
        # 只要列表中的数据有一个为 None 则返回False
        if not all([username,password,password2,mobile,allow,sms_code_client]):
            # from django import http
            return http.HttpResponseBadRequest('参数不全')
        # ④验证用户名
        if not re.match(r'^[0-9a-zA-Z_-]{5,20}$',username):
            return http.HttpResponseBadRequest('用户名不满足条件')

        # ⑤验证密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
            return http.HttpResponseBadRequest('密码格式不正确')
        # ⑥验证确认密码
        if password2!=password:
            return http.HttpResponseBadRequest('密码不一致')
        # ⑦验证手机号
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return http.HttpResponseBadRequest('手机号不符合规则')
        # ⑧验证是否同意协议
        if allow != 'on':
            return http.HttpResponseBadRequest('您未同意协议')
        #验证 用户提交的短信验证码和redis的短信验证码是否一致
        # 连接redis
        redis_conn = get_redis_connection('code')
        # 获取redis中的短信验证码
        sms_code_server = redis_conn.get('sms_%s'%mobile)
        # 判断redis中的短信验证码是否过期
        if not sms_code_server:
            return http.HttpResponseBadRequest("短信验证码过期")
        # 对比
        if sms_code_server.decode() != sms_code_client:
            return http.HttpResponseBadRequest('验证码不一致')




        # ⑨保存数据,我们要把数据保存在数据库中
        try:
            # create_user 是系统提供的 自动对密码进行加密的方法,同时也会会创建用户
            user = User.objects.create_user(
                username=username,
                password=password,
                mobile=mobile
            )
        except Exception as e:
            logger.error(e)
            return render(request,'register.html',context={'register_errmsg':'创建用户失败'})

        login(request,user)
        # ⑩跳转首页,返回相应
        return redirect(reverse('contents:index'))
        # return http.HttpResponse('ok')
class RegisterUsernameCountView(View):
    def get(self,request,username):
        count = User.objects.filter(username=username).count()
        return http.JsonResponse({'count':count})
class RegisterMobileCountView(View):
    def get(self,request,mobile):
        count = User.objects.filter(mobile=mobile).count()
        return http.JsonResponse({"count":count})
class LoginView(View):
    def get(self,request):
        return render(request,'login.html')
    def post(self,request):
        # 1.接收数据
        data = request.POST
        # 2.获取数据
        username = data.get("username")
        password = data.get('pwd')
        remembered = data.get('remembered')
        # 3.验证是否齐全(用户名和密码都要传过来)
        if not all([username,password]):
            return http.HttpResponseBadRequest('参数不齐')
        # 4.判断用户名是否符合规则
        if not re.match(r'^[0-9a-zA-Z_-]{5,20}',username):
            return http.HttpResponseBadRequest('用户名格式不对')
        # 5.判断密码是否符合规则
        if not re.match(r'^[0-9a-zA-Z]{8,20}',password):
            return http.HttpResponseBadRequest('密码格式不正确')
        # 6.验证用户名和密码是否正确
        from django.contrib.auth import authenticate
        user = authenticate(username=username,password=password)
        if user is None:
            return http.HttpResponseBadRequest("用户名或密码有错误啊老弟")
        # 7.保持会话
        login(request,user)
        if remembered != 'on':
            #表示关闭浏览器以后session自毁
            request.session.set_expiry(0)
        else:
            #表示记住登陆状态session根据产品需求设置失效时间 这里用默认值两周
            request.session.set_expiry(None)

        next = request.GET.get('next')
        if next :
            response = redirect(next)
        else:
            response = redirect(reverse("contents:index"))
        # 8.返回响应
        # response = redirect(reverse('contents:index'))
        if remembered != 'on':
            response.set_cookie('username',user.username,max_age=None)
        else:
            response.set_cookie('username',user.username,max_age=14*24*3600)

        return response
#1.导入系统的logout包
from django.contrib.auth import logout
#定义类视图
class LogoutView(View):
    #用get接收请求
    def get(self,request):
        #调用系统的退出 logout
        logout(request)
        #返回首页
        response = redirect(reverse('contents:index'))
        #在返回首页之前删除cookie中的username
        response.delete_cookie('username')
        #返回响应
        return response
from django.contrib.auth.mixins import LoginRequiredMixin
class UserInfoView(LoginRequiredMixin,View):
    def get(self,request):
        context = {
            "username":request.user.username,
            "mobile":request.user.mobile,
            "email":request.user.email,
            "email_active":request.user.email_active,
        }
        return render(request,"user_center_info.html",context=context)
from django.contrib.auth.mixins import LoginRequiredMixin
class EmailView(LoginRequiredJsonMixin,View):
    def put(self,request):
        body=request.body
        body_str = body.decode()
        data = json.loads(body_str)
        email=data.get('email')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数错误'})
        try:
            request.user.email=email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '数据库错误'})
        from django.core.mail import send_mail
        # 1.subject             主题
        subject = '主题'
        # 2.message             消息
        message = ''
        verify_url =generic_verify_email_url(request.user.id)
        # 3.from_email          谁发送的
        from_email = 'qi_rui_hua@163.com'
        # 4.recipient_list      收件人列表[]
        recipient_list = [email]
        html_message = '<p>尊敬的用户您好！</p>' \
                   '<p>感谢您使用美多商城。</p>' \
                   '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                   '<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)
        # send_mail(
        #     subject = subject,
        #     message = message,
        #     from_email = from_email,
        #     recipient_list =recipient_list
        # )
        from celery_tasks.email.tasks import send_verify_email
        send_verify_email.delay(
            subject=subject,
            message=message,
            from_email=from_email,
            recipient_list=recipient_list,
            html_message=html_message
        )
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
class EmailVerifyView(View):
    def get(self,request):
        token = request.GET.get('token')
        if token is None:
            return http.HttpResponseBadRequest('参数错误')
        user_id = check_verify_email_token(token)
        if user_id is None:
            return http.HttpResponseBadRequest('参数错误')
        try:
            user = User.objects.get(id=user_id)
            if user is not None:
                user.email_active = True
                user.save()
        except User.DoesNotExist:
            return http.HttpResponseBadRequest('参数错误')
        return redirect(reverse('users:info'))